package j.framework.qmd.core;

import com.alibaba.fastjson.annotation.JSONField;
import j.util.New;
import j.util.SpringBeans;
import j.util.StringUtils;

import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * User: jason
 * Date: 14-7-18 上午10:31
 */
public class QueryMetadata implements Serializable{

    /**
     * 查询的footer定义
     */
    private List<QueryFieldFooter> footers;

    private List<QueryOperation> operations;

    private String footerClause;

    public String getFooterClause() {
        return footerClause;
    }

    public String getDefaultSortNames(){
        if(defaultQuerySort == null){
            return null;
        }
        StringBuilder s = new StringBuilder();
        for(QuerySort sort : defaultQuerySort){
            s.append(sort.getFieldKey()).append(",");
        }
        s.deleteCharAt(s.length()-1);
        return s.toString();
    }
    public String getDefaultOrders(){
        if(defaultQuerySort == null){
            return null;
        }
        StringBuilder s = new StringBuilder();
        for(QuerySort sort : defaultQuerySort){
            s.append(sort.getOrderBy().toLowerCase()).append(",");
        }
        s.deleteCharAt(s.length()-1);
        return s.toString();
    }

    private QueryDataHandler handler;
    private Boolean isQueryDataHandler = null;

    public QueryDataHandler getQueryDataHandler(String str){
        if(isQueryDataHandler!=null && !isQueryDataHandler){
            return null;
        }
        if(StringUtils.isNullOrEmpty(dataHandlerClassName)){
            return null;
        }
        if(handler == null){
            synchronized (QueryMetadata.class){
                if(handler == null){
                    try{
                        Class<?> clazz = Class.forName(dataHandlerClassName);
                        if(clazz.getInterfaces().length>=1){
                            for(Class<?> face : clazz.getInterfaces()){
                                if(face.equals(QueryDataHandler.class)){
                                    handler = (QueryDataHandler) clazz.newInstance();
                                    isQueryDataHandler = true;
                                    break;
                                }
                            }
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }
        isQueryDataHandler = false;
        return handler;
    }

    private Map<String,QueryFieldMetadata> fieldMetadataMap = New.lMap();
    private Map<String,String> fieldNameIdMapper = New.map();
    public final Map<String,DataGridColumn> columns = New.lMap();
    public final Map<String,DataGridColumn> plainColumns = New.map();

    private List<DataColumn> primaryKeys;

    private List<QuerySort> defaultQuerySort;

    public List<DataColumn> getPrimaryKeys() {
        return primaryKeys;
    }
    public void setPrimaryKeys(List<DataColumn> primaryKeys) {
        this.primaryKeys = primaryKeys;
    }

    public List<QuerySort> getDefaultQuerySort() {
        return defaultQuerySort;
    }
    public void setDefaultQuerySort(List<QuerySort> defaultQuerySort) {
        this.defaultQuerySort = defaultQuerySort;
    }

    public QueryFieldMetadata getFieldMetadata(String key){
        QueryFieldMetadata qfmd = fieldMetadataMap.get(key);
        if(qfmd == null){
            qfmd = fieldMetadataMap.get(fieldNameIdMapper.get(key));
        }
        return qfmd;
    }
    public QueryFieldMetadata getFieldMetadataByFieldName(String fieldName){
        String id = fieldNameIdMapper.get(fieldName);
        return fieldMetadataMap.get(id);
    }

    private boolean hasGroupColumns = false;
    private int groupDepth = 1;

    public boolean isHasGroupColumns() {
        return hasGroupColumns;
    }

    public int getGroupDepth() {
        return groupDepth;
    }

    public void putFieldMetadata(QueryFieldMetadata md){
        fieldMetadataMap.put(md.getFieldId(),md);
        fieldNameIdMapper.put(md.getFieldName(),md.getFieldId());
        if(md.isSuppressible()){
            //这列不显示，直接不处理
            return;
        }
        DataGridColumn dgColumn = new DataGridColumn();
        dgColumn.setTitle(md.getDisplayName());
        dgColumn.setFieldKey(md.getFieldId());
        dgColumn.setDisplayOrder(md.getDisplayOrder());
        String[] tags;
        if(StringUtils.isNotEmpty(md.getDisplayNameTag())){
            //这是多表头
            if(!hasGroupColumns){
                hasGroupColumns = true;
            }
            tags = md.getDisplayNameTag().split("\\|");
            if(tags.length==groupDepth){
                groupDepth = tags.length+1;
            }
            DataGridColumn columnByTag = null;
            String lastTag = tags[0];
            for(String tag : tags){
                columnByTag = plainColumns.get(lastTag);
                if(columnByTag==null){
                    columnByTag = new DataGridColumn();
                    columnByTag.setTitle(tag);
                    columnByTag.setDisplayOrder(md.getDisplayOrder());
                    columnByTag.setSuperHeader(true);
                    columns.put(columnByTag.getTitle(),columnByTag);
                }else{
                    columns.put(tag,columnByTag);
                }
                plainColumns.put(columnByTag.getTitle(),columnByTag);
                lastTag = tag;
            }
            if(columnByTag!=null){
                columnByTag.subColumns.put(dgColumn.getTitle(),dgColumn);
            }
            /*columnByTag = columns.get(md.getDisplayNameTag());
            if(columnByTag==null){
                columnByTag = new DataGridColumn();
                columnByTag.setTitle(md.getDisplayNameTag());
                columnByTag.setDisplayOrder(md.getDisplayOrder());
                columnByTag.setSuperHeader(true);
                columnByTag.subColumns.put(md.getDisplayName(),dgColumn);
                columns.put(columnByTag.getTitle(),columnByTag);
            }else{
                columnByTag.subColumns.put(dgColumn.getTitle(),dgColumn);
            }*/
        }else{
            //没有多表头
            columns.put(dgColumn.getTitle(),dgColumn);
        }
    }

    public Collection<QueryFieldMetadata> getFieldMetadataList(){
        return fieldMetadataMap.values();
    }

    public String getUserInfo(){
        return "";
    }

    private String queryId;

    private String queryKey;

    private String functionId;//所属模块

    private String name;//查询名称

    private String querySql;//查询语句

    private boolean storeProcedure;

    private boolean namedSql;

    private boolean pagingSupported;//是否支持分页

    private Integer defaultPageSize; //默认页大小

    private String defaultPageList;//默认页大小列表

    private boolean footerSupported;//是否支持显示footer

    private String footerOptions;//footer选项

    private boolean operatorSupported;

    private String dataHandlerClassName;

    private String buildWhereMethodName;

    private boolean columnMovingSupported;

    private boolean multiColumnSortedSupported;//是否支持多列排序

    private String rowClick;

    private String rowStyler;

    private boolean multiSelectSupported;

    private String addedUserId;

    private Date addedTime;

    private boolean showByTree;

    private DataColumn treeField;

    private boolean showRowNumbers;

    private Integer frozenLeftColumns;
    private Integer frozenRightColumns;
    private Integer frozenTopRows;

    public String getQueryId() {
        return queryId;
    }

    public void setQueryId(String queryId) {
        this.queryId = queryId;
    }

    public String getQueryKey() {
        return queryKey;
    }

    public void setQueryKey(String queryKey) {
        this.queryKey = queryKey;
    }

    public String getFunctionId() {
        return functionId;
    }

    public void setFunctionId(String functionId) {
        this.functionId = functionId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getQuerySql() {
        return querySql;
    }

    public void setQuerySql(String querySql) {
        this.querySql = querySql;
    }

    public boolean isStoreProcedure() {
        return storeProcedure;
    }
    public void setStoreProcedure(boolean isStoreProcedure) {
        this.storeProcedure = isStoreProcedure;
    }

    public boolean isNamedSql() {
        return namedSql;
    }
    public void setNamedSql(boolean isNamedSql) {
        this.namedSql = isNamedSql;
    }

    public boolean isPagingSupported() {
        return pagingSupported;
    }

    public void setPagingSupported(boolean pagingSupported) {
        this.pagingSupported = pagingSupported;
    }

    public boolean isFooterSupported() {
        return footerSupported;
    }

    public void setFooterSupported(boolean footerSupported) {
        this.footerSupported = footerSupported;
    }

    public String getFooterOptions() {
        return footerOptions;
    }

    public void setFooterOptions(String footerOptions) {
        this.footerOptions = footerOptions;
    }

    public String getDataHandlerClassName() {
        return dataHandlerClassName;
    }
    public void setDataHandlerClassName(String dataHandlerClassName) {
        this.dataHandlerClassName = dataHandlerClassName;
    }
    private Object springBean = null;
    @JSONField(serialize = false)
    public Object getSpringBean(){
        if(( isQueryDataHandler != null && isQueryDataHandler )|| StringUtils.isNullOrEmpty(dataHandlerClassName)){
            return null;
        }
        if(springBean==null){
            synchronized (QueryMetadata.class){
                if(springBean == null){
                    try {
                        Class<?> clazz = Class.forName(dataHandlerClassName);
                        springBean = SpringBeans.getBean(clazz);
                    }catch (ClassNotFoundException e) {
                        throw new RuntimeException(String.format("SpringBean[%s]没有定义，请确定！",dataHandlerClassName));
                    }
                }
            }
        }
        return springBean;
    }

    public String getBuildWhereMethodName() {
        return buildWhereMethodName;
    }
    public void setBuildWhereMethodName(String buildWhereMethodName) {
        this.buildWhereMethodName = buildWhereMethodName;
    }

    public boolean isOperatorSupported() {
        return operatorSupported;
    }
    public void setOperatorSupported(boolean operatorSupported) {
        this.operatorSupported = operatorSupported;
    }

    public String getAddedUserId() {
        return addedUserId;
    }

    public void setAddedUserId(String addedUserId) {
        this.addedUserId = addedUserId;
    }

    public Date getAddedTime() {
        return addedTime;
    }

    public void setAddedTime(Date addedTime) {
        this.addedTime = addedTime;
    }

    public boolean isColumnMovingSupported() {
        return columnMovingSupported;
    }

    public void setColumnMovingSupported(boolean columnMovingSupported) {
        this.columnMovingSupported = columnMovingSupported;
    }

    public boolean isMultiColumnSortedSupported() {
        return multiColumnSortedSupported;
    }

    public void setMultiColumnSortedSupported(boolean multiColumnSortedSupported) {
        this.multiColumnSortedSupported = multiColumnSortedSupported;
    }

    public String getRowClick() {
        return rowClick;
    }

    public void setRowClick(String rowClick) {
        this.rowClick = rowClick;
    }

    public String getRowStyler() {
        return rowStyler;
    }

    public void setRowStyler(String rowStyler) {
        this.rowStyler = rowStyler;
    }

    public boolean isMultiSelectSupported() {
        return multiSelectSupported;
    }

    public void setMultiSelectSupported(boolean multiSelectSupported) {
        this.multiSelectSupported = multiSelectSupported;
    }

    public boolean isShowByTree() {
        return showByTree;
    }
    public void setShowByTree(boolean showByTree) {
        this.showByTree = showByTree;
    }

    public DataColumn getTreeField() {
        return treeField;
    }
    public void setTreeField(DataColumn treeField) {
        this.treeField = treeField;
    }

    public boolean isShowRowNumbers() {
        return showRowNumbers;
    }
    public void setShowRowNumbers(boolean showRowNumbers) {
        this.showRowNumbers = showRowNumbers;
    }

    public String getDefaultPageList() {
        return defaultPageList;
    }

    public void setDefaultPageList(String defaultPageList) {
        this.defaultPageList = defaultPageList;
    }

    public Integer getDefaultPageSize() {
        return defaultPageSize;
    }

    public void setDefaultPageSize(Integer defaultPageSize) {
        this.defaultPageSize = defaultPageSize;
    }

    public Integer getFrozenLeftColumns() {
        return frozenLeftColumns;
    }
    public void setFrozenLeftColumns(Integer frozenLeftColumns) {
        this.frozenLeftColumns = frozenLeftColumns;
    }

    public Integer getFrozenRightColumns() {
        return frozenRightColumns;
    }
    public void setFrozenRightColumns(Integer frozenRightColumns) {
        this.frozenRightColumns = frozenRightColumns;
    }

    public Integer getFrozenTopRows() {
        return frozenTopRows;
    }
    public void setFrozenTopRows(Integer frozenTopRows) {
        this.frozenTopRows = frozenTopRows;
    }

    public List<QueryFieldFooter> getFooters() {
        return footers;
    }
    public void setFooters(List<QueryFieldFooter> footers) {
        this.footers = footers;
        if(null!=footers && footers.size()>0){
            StringBuilder s = new StringBuilder();
            int i=0;
            String footerFieldName;
            QueryFieldMetadata qfmd;
            for(QueryFieldFooter footer : footers) {
                qfmd = getFieldMetadata(footer.getFieldId());
                if (qfmd == null) {
                    continue;
                }
                if (i++ > 0) {
                    s.append(",");
                }
                footerFieldName = qfmd.getFieldName();
                if (StringUtils.isNotEmpty(qfmd.getTableAliasName())) {
                    footerFieldName = qfmd.getTableAliasName() + "." + footerFieldName;
                }
                s.append(footer.getCalcType()).append("(").append(footerFieldName).append(")");
                s.append(" as ").append(qfmd.getFieldName());
            }
            if(i>0){
                footerClause = s.toString();
            }
        }
    }

    public List<QueryOperation> getOperations() {
        return operations;
    }
    public void setOperations(List<QueryOperation> operations) {
        this.operations = operations;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        QueryMetadata that = (QueryMetadata) o;

        if (queryId != null ? !queryId.equals(that.queryId) : that.queryId != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        return queryId != null ? queryId.hashCode() : 0;
    }
}
